using Godot;
using Godot.Collections;

[Tool]
public partial class MapEditorPluginUI : Control
{
  [Export]
  private LineEdit _input;
  [Export]
  private FileDialog _dialog;

  private EditorPlugin _plug;
  private EditorInterface _face;
  public override void _Ready()
  {
    _plug = new EditorPlugin();
    _face = EditorInterface.Singleton;
  }

  readonly string _savePath = "res://Resource/MapData/";

  public void OnButtonClick()
  {
    var sels = _face.GetSelection().GetSelectedNodes();
    if (sels.Count != 1)
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }
    if (_input.Text.Trim().Length == 0)
    {
      GD.PrintErr("请填写地图名称");
      return;
    }
    Node sel = sels[0];
    if (sel.GetType() != typeof(TileMap))
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }
    BattleMapDataStruct mapData = new();
    mapData.MapName = _input.Text;
    TileMap map = (TileMap)sel;
    Array<Vector2I> cells = map.GetUsedCells(0);
    mapData.Cells = new System.Collections.Generic.List<BattleMapCellData>();
    foreach (var item in cells)
    {
      var id = map.GetCellSourceId(0, new Vector2I(item.X, item.Y));
      var coords = map.GetCellAtlasCoords(0, new Vector2I(item.X, item.Y));
      mapData.Cells.Add(BattleMapCellData.Init(item, id, coords, id));
    }
    string result = parseMapData(mapData);
    FileAccess file = FileAccess.Open(_savePath + _input.Text + ".json", FileAccess.ModeFlags.Write);
    file.StoreString(result);
    file.Close();
  }

  private string parseMapData(BattleMapDataStruct data)
  {
    Dictionary<string, Variant> dic = new();
    dic.Add("MapName", data.MapName);

    Array<Dictionary<string, Variant>> cells = new();
    foreach (var item in data.Cells)
    {
      Dictionary<string, Variant> cell = new();
      cell.Add("X", item.X);
      cell.Add("Y", item.Y);
      cell.Add("SourceId", item.SourceId);
      Dictionary<string, Variant> atlasCoords = new();
      atlasCoords.Add("X", item.AtlasCoords.X);
      atlasCoords.Add("Y", item.AtlasCoords.Y);
      cell.Add("AtlasCoords", atlasCoords);
      cell.Add("Cost", item.BaseCost);
      cells.Add(cell);
    }

    dic.Add("Cells", cells);

    return Json.Stringify(dic);
  }

  public void OnLoadClick()
  {
    var sels = _face.GetSelection().GetSelectedNodes();
    if (sels.Count != 1)
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }
    Node sel = sels[0];
    if (sel.GetType() != typeof(TileMap))
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }
    _dialog.Show();
  }

  public void OnSelectedFile(string path)
  {
    var sels = _face.GetSelection().GetSelectedNodes();
    if (sels.Count != 1)
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }
    Node sel = sels[0];
    if (sel.GetType() != typeof(TileMap))
    {
      GD.PrintErr("请选择TileMap节点");
      return;
    }

    var file = FileAccess.Open(path, FileAccess.ModeFlags.Read);
    var str = file.GetAsText();
    file.Close();
    var json = new Json();
    var result = json.Parse(str);
    if (result != Error.Ok)
    {
      GD.Print("Error :", json.GetErrorMessage());
      return;
    }
    var dic = new Dictionary<string, Variant>((Dictionary)json.Data);
    var mapData = parseJsonData(dic);
    // 修改TileMap
    buildTileMap(mapData, (TileMap)sel);
  }

  private BattleMapDataStruct parseJsonData(Dictionary<string, Variant> dic)
  {
    BattleMapDataStruct data = new();
    data.MapName = _input.Text = dic["MapName"].ToString();
    data.Cells = new System.Collections.Generic.List<BattleMapCellData>();
    foreach (var item in dic["Cells"].AsGodotArray<Dictionary<string, Variant>>())
    {
      var X = item["X"].AsInt32();
      var Y = item["Y"].AsInt32();
      var SourceId = item["SourceId"].AsInt32();
      var coordDic = new Dictionary<string, Variant>((Dictionary)item["AtlasCoords"]);
      var AtlasCoords = new Vector2I(coordDic["X"].AsInt32(), coordDic["Y"].AsInt32());
      var cost = item["Cost"].AsInt32();
      var cell = new BattleMapCellData(X, Y, SourceId, AtlasCoords, cost);
      data.Cells.Add(cell);
    }
    return data;
  }

  private void buildTileMap(BattleMapDataStruct data, TileMap tileMap)
  {
    tileMap.Clear();
    data.Cells.ForEach(item =>
    {
      tileMap.SetCell(0, new Vector2I(item.X, item.Y), item.SourceId, item.AtlasCoords);
    });
  }
}
